package com.ideaaedi.springcloud.jd.commonspring.enhancer;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.converters.longconverter.LongStringConverter;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.ideaaedi.commonds.time.DateTimeConverter;
import com.ideaaedi.springcloud.jd.commonds.converter.EasyExcelConverter;
import com.ideaaedi.springcloud.jd.commonds.entity.ExcelExportSettings;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.Ordered;
import org.springframework.http.MediaType;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 默认的excel导出执行器
 *
 * @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img
 * src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
 * @since 2021.0.1.F
 */
@Slf4j
@Component
public class DefaultExcelExportExecutor implements ExcelExportExecutor {
    
    private static final String CLASS_NAME = DefaultExcelExportExecutor.class.getName();
    
    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
    
    @Override
    public <T> boolean support(@NonNull Class<T> clazz) {
        return true;
    }
    
    @Override
    public <T> void export(@NonNull ExcelExportSettings excelExportSettings, @NonNull Class<T> clazz,
                           @Nullable List<T> dataList, @NonNull HttpServletResponse httpServletResponse) {
        try {
            log.info("Change response json to do excel export start. Hit -> {} curr clazz is -> {}.", CLASS_NAME, clazz.getName());
            String excelFilename = excelExportSettings.getExcelFilename();
            excelFilename = StringUtils.isBlank(excelFilename) ? DateTimeConverter.COMPACT_DATE_TIME.now() : excelFilename;
            excelFilename = URLEncoder.encode(excelFilename, StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");
            String sheetName = excelExportSettings.getSheetName();
            List<String> includeColumnFieldNames = excelExportSettings.getIncludeColumnFieldNames();
            List<String> excludeColumnFiledNames = excelExportSettings.getExcludeColumnFiledNames();
    

            httpServletResponse.setContentType(MediaType.APPLICATION_OCTET_STREAM.getType());
            httpServletResponse.setCharacterEncoding(StandardCharsets.UTF_8.name());
            // URLEncoder.encode防止中文乱码
            httpServletResponse.setHeader("Content-disposition", "attachment;filename*=utf-8''" + excelFilename + ".xlsx");
            ExcelWriterBuilder writerBuilder = EasyExcel.write(httpServletResponse.getOutputStream(), clazz);
            writerBuilder.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy());
            // 转换器优先级： 字段上通过@ExcelProperty指定转换器 > 这里注册的转换器 > easyexcel内置的转换器
            writerBuilder.registerConverter(new LongStringConverter());
            writerBuilder.registerConverter(new EasyExcelConverter.CertTypeEnumConverter());
            writerBuilder.registerConverter(new EasyExcelConverter.UserTypeEnumConverter());
            // 这里需要设置不关闭流
            writerBuilder.autoCloseStream(Boolean.FALSE);
            if (!CollectionUtils.isEmpty(includeColumnFieldNames)) {
                writerBuilder.includeColumnFieldNames(includeColumnFieldNames);
            }
            if (!CollectionUtils.isEmpty(excludeColumnFiledNames)) {
                writerBuilder.excludeColumnFieldNames(excludeColumnFiledNames);
            }
            writerBuilder.sheet(sheetName).doWrite(dataList);
            log.info("Change response json to do excel export end.");
        } catch (Exception e) {
            log.error("Change response json to do excel export occur exception.", e);
            if (!httpServletResponse.isCommitted()) {
                httpServletResponse.reset();
                httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
                httpServletResponse.setCharacterEncoding(StandardCharsets.UTF_8.name());
            }
            throw new RuntimeException(e);
        }
    }
}
